﻿using System;
using System.Data;
using System.Drawing;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;

namespace System
{
    /// <summary>
    /// 工具类
    /// </summary>
    public partial class Utils {
        public static T GetObjTranNull<T>(object obj) {
            try {
                if(obj == null) {
                    return (T)System.Convert.ChangeType("",typeof(T));
                } else {
                    if(obj.GetType() == typeof(T))
                        return (T)obj;
                }
                return (T)System.Convert.ChangeType(obj,typeof(T));
            } catch { }
            return default(T);
        }
        #region 截取字符串
        public static string GetFirstString(string stringToSub,int length,bool isCut = false) {
            if(string.IsNullOrEmpty(stringToSub)) return stringToSub;
            string cut = "";
            if(isCut) {
                cut = "...";
            }
            return stringToSub.Length <= length ? stringToSub : stringToSub.Substring(0,length) + cut;
        }
        #endregion
        public static string GetRandomColor() {
            Random RandomNum_First = new Random(GetRandomSeed(0));
            Thread.Sleep(100);
            Random RandomNum_Sencond = new Random(GetRandomSeed(1));
            //  为了在白色背景上显示，尽量生成深色
            int int_Red = RandomNum_First.Next(256);
            int int_Green = RandomNum_Sencond.Next(256);
            int int_Blue = (int_Red + int_Green > 400) ? 0 : 400 - int_Red - int_Green;
            int_Blue = (int_Blue > 255) ? 255 : int_Blue;
            Color color = Color.FromArgb(int_Red,int_Green,int_Blue);
            string strColor = "#" + Convert.ToString(color.ToArgb(),16).PadLeft(8,'0').Substring(2,6);
            return strColor;
        }
        //获取随机种子
        public static int GetRandomSeed(int bte = 4) {
            byte[] bytes = new byte[4];
            using(var rng = new System.Security.Cryptography.RNGCryptoServiceProvider()) {
                rng.GetBytes(bytes);
            }

            return BitConverter.ToInt32(bytes, 0);
        }
        //保留两位小数但不四舍五入
        public static decimal ToDecimal(double number,int weishu = 2) {
            return ToDecimal(decimal.Parse(number.ToString()),weishu);
        }
        //保留两位小数但不四舍五入
        public static decimal ToDecimal(decimal number,int weishu = 2) {
            try {
                //保留两位小数但不四舍五入
                var tmp = decimal.Parse(Regex.Match(number.ToString(),@"[d]+.[d]{0,2}").Value);
                return tmp;
            } catch(Exception) {
                try {
                    return Math.Round(GetObjTranNull<decimal>(number),weishu,MidpointRounding.AwayFromZero);
                } catch(Exception) {
                    return GetObjTranNull<decimal>(number);
                }
            }
        }
        //时间计算
        public static int GetGongLing(string startDate,string endDate) {
            try {
                if(string.IsNullOrWhiteSpace(startDate)) return 0;
                if(string.IsNullOrWhiteSpace(endDate)) return 0;
                DateTime StartDate = DateTime.Parse(startDate);
                DateTime EndDate = DateTime.Parse(endDate);
                int lngDateDiffValue = 0;
                System.TimeSpan TS = new System.TimeSpan(EndDate.Ticks - StartDate.Ticks);
                lngDateDiffValue = TS.Days / 365;
                return (lngDateDiffValue);
            } catch(Exception) {
                return 0;
            }
        }
        public static T Run<T>(Func<T> func) {
            DateTime startTime = DateTime.Now;
            T _obj = default(T);
            try {
                _obj = func();
            } catch(Exception ex) {
                Logger.LogError("run:",ex);
            }
            DateTime endTime = DateTime.Now;
            var ts = endTime - startTime;
            Console.WriteLine("运行耗时：" + (endTime - startTime).TotalMilliseconds.ToString() + "ms");
            return _obj;
        }
        public static void Run(Action action,int stepTotal = 10000,string description = "") {
            DateTime startTime = DateTime.Now;
            for(int i = 0;i < stepTotal;i++) {
                action();
            }
            DateTime endTime = DateTime.Now;
            var ts = endTime - startTime;
            Console.WriteLine(description + "_运行“" + stepTotal.ToString() + "”次耗时：" + (endTime - startTime).TotalMilliseconds.ToString() + "ms");
        }

        public static T GetOrAddCache<T>(string key, Func<T> func = null) {
            string cacheKey = "rsxt_" + key;
            var obj = MemoryCacheHelper.Get(cacheKey);
            if(obj == null) {
                if(func != null) {
                    var _obj = func();
                    if(_obj != null) {
                        MemoryCacheHelper.Set(cacheKey, _obj);
                    }
                    return _obj;
                }
                return default(T);
            } else {
                return (T)obj;
            }
        }

        #region 唯一订单号生成

        /// <summary>
        /// 唯一订单号生成
        /// </summary>
        /// <returns></returns>
        public static string GenerateOrderNumber() {
            string strDateTimeNumber = DateTime.Now.ToString("yyyyMMddHHmmssffff");
            string strRandomResult = NextRandom(1000,1).ToString("0000");
            return strDateTimeNumber + strRandomResult;
        }
        /// <summary>
        /// 参考：msdn上的RNGCryptoServiceProvider例子
        /// </summary>
        /// <param name="numSeeds"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        private static int NextRandom(int numSeeds,int length) {
            // Create a byte array to hold the random value.
            byte[] randomNumber = new byte[length];
            // Create a new instance of the RNGCryptoServiceProvider.
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            // Fill the array with a random value.
            rng.GetBytes(randomNumber);
            // Convert the byte to an uint value to make the modulus operation easier.
            uint randomResult = 0x0;
            for(int i = 0;i < length;i++) {
                randomResult |= ((uint)randomNumber[i] << ((length - 1 - i) * 8));
            }
            return (int)(randomResult % numSeeds) + 1;
        }
        #endregion

        #region  DataTable追加合计
        /// <summary>
        /// DataTable追加合计
        /// </summary>
        /// <param name="dt">数据源</param>
        /// <param name="sumColumns">给哪一列赋值"合计"字符串</param>
        /// <returns></returns>
        public static DataTable GetSumToDatatable(DataTable dt,string sumColumns) {
            string ColumnName = "";
            try {
                DataRow sum = dt.NewRow();
                sum[sumColumns] = "合计";
                foreach(DataColumn col in dt.Columns) {
                    Type dataType = col.DataType;
                    ColumnName = col.ColumnName;
                    if(dataType.Name == "Decimal" || dataType.Name == "Int") {
                        sum[ColumnName] = dt.Compute($"sum({ColumnName})","TRUE");
                    }

                }
                dt.Rows.Add(sum);
                return dt;
            } catch(Exception ex) {
                Logger.LogError($"GetSumToDatatable:{ColumnName}",ex);
                return dt;
            }

        }
        /// <summary>
        /// DataTable分页
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="PageIndex"></param>
        /// <param name="PageSize"></param>
        /// <returns></returns>
        public static DataTable GetPageToDataTable(DataTable dt,int PageIndex,int PageSize) {
            if(PageIndex == 0)
                return dt;//0页代表每页数据，直接返回
            if(dt == null) {
                DataTable table = new DataTable();
                return table;
            }
            DataTable newdt = dt.Copy();
            newdt.Clear();//copy dt的框架
            int rowbegin = (PageIndex - 1) * PageSize;
            int rowend = PageIndex * PageSize;//要展示的数据条数
            if(rowbegin >= dt.Rows.Count)
                return newdt;//源数据记录数小于等于要显示的记录，直接返回dt
            if(rowend > dt.Rows.Count)
                rowend = dt.Rows.Count;
            for(int i = rowbegin;i <= rowend - 1;i++) {
                DataRow newdr = newdt.NewRow();
                DataRow dr = dt.Rows[i];
                foreach(DataColumn column in dt.Columns) {
                    newdr[column.ColumnName] = dr[column.ColumnName];
                }
                newdt.Rows.Add(newdr);
            }
            return newdt;
        }
        #endregion

        public static string FilterSql(string s) {
            if(string.IsNullOrEmpty(s)) return string.Empty;
            s = s.Trim().ToLower();
            //s = ClearScript(s);
            s = s.Replace("=","");
            s = s.Replace("'","");
            s = s.Replace(";","");
            s = s.Replace(" or ","");
            s = s.Replace("select","");
            s = s.Replace("update","");
            s = s.Replace("insert","");
            s = s.Replace("delete","");
            s = s.Replace("declare","");
            s = s.Replace("exec","");
            s = s.Replace("drop","");
            s = s.Replace("create","");
            s = s.Replace("%","");
            s = s.Replace("--","");
            return s;
        }

        /// <summary>
        /// 提取字符串中的汉字
        /// </summary>
        public static string GetChineseWord(string oriText)
        {
            try
            {
                string x = @"[\u4E00-\u9FFF]+";
                MatchCollection Matches = Regex.Matches(oriText, x, RegexOptions.IgnoreCase);
                StringBuilder sb = new StringBuilder();
                foreach (Match NextMatch in Matches)
                {
                    sb.Append(NextMatch.Value);
                }
                return sb.ToString();
            }
            catch
            {
                return "";
            }
        }
    }
}
